package xj.graph2d.template;

import java.util.Map;

import xj.graph2d.ArrowAttr;
import xj.graph2d.CompoundDrawShape;
import xj.graph2d.DrawAttr;
import xj.graph2d.DrawShape;
import xj.graph2d.DrawShapeConstants;
import xj.graph2d.EllipseShape;
import xj.graph2d.GraphEdgeBase;
import xj.graph2d.GraphNodeBase;
import xj.graph2d.LineShape;
import xj.graph2d.RectangleShape;
import xj.graph2d.TextShape;
import xj.graph2d.shapes.CubicCurveShape;
import xj.graph2d.shapes.GraphEdgeShape;
import xj.graph2d.shapes.OrthogonalLineShape;
import xj.graph2d.shapes.PolyCurveShape;
import xj.graph2d.shapes.QuadCurveShape;
import xj.graph2d.shapes.RectangularShape;
import xj.graph2d.shapes.RoundRectangleShape;
import xj.graph2d.shapes.ShapeConstants;
import xj.graph2d.template.uml.UMLActivityFlowModelListener;
import xj.graph2d.template.uml.UMLActivityNodeModelListener;
import xj.model.uml.ActivityFlow;
import xj.model.uml.ActivityNode;

public class UMLActivityDiagramTemplate extends UMLTemplate {

  // Activity Machine Diagram

  static String[][] activityDiagramGapToolNames = {
    { "Object1", "Object2", "Action", "DataStore", },
    { "ForkNode", "ForkNodeH", "JoinNode", "JoinNodeH", }, 
    { "AcceptEvent1", "AcceptEvent2", "SendEvent", "FinalFlow", },
    { "InitialNode", "FinalNode", "Decision", "MergeNode", }, 
  };

  static String[][] activityNodeEdgeToolNames = {
    // TOP_SIDE
    { "Flow1-1-Popup", "Flow1-2-Popup",  
      "Flow2-1-Popup", "Flow2-2-Popup",}, 

    // BOTTOM_SIDE 
    { "Flow1-3-Popup", "Flow1-4-Popup", 
      "Flow2-3-Popup", "Flow2-4-Popup",},  

    // LEFT_SIDE
    { "Flow1-5-Popup", "Flow1-6-Popup", 
      "Flow2-5-Popup", "Flow2-6-Popup",},  

    // RIGHT_SIDE
    { "Flow1-7-Popup", "Flow1-8-Popup", 
      "Flow2-7-Popup", "Flow2-8-Popup",},  
  };

  static String[][] initActivityNodeEdgeToolNames = {
    // TOP_SIDE
    { "Flow1-1-Popup", "Flow2-1-Popup", },

    // BOTTOM_SIDE 
    { "Flow1-4-Popup", "Flow2-4-Popup", },  

    // LEFT_SIDE
    { "Flow1-6-Popup", "Flow2-6-Popup", },  

    // RIGHT_SIDE
    { "Flow1-7-Popup", "Flow2-7-Popup", },
  };

  static String[][] finalActivityNodeEdgeToolNames = {
    // TOP_SIDE
    { "Flow1-2-Popup", "Flow2-2-Popup", }, 

    // BOTTOM_SIDE 
    { "Flow1-3-Popup", "Flow2-3-Popup", },

    // LEFT_SIDE
    { "Flow1-5-Popup", "Flow2-5-Popup", },

    // RIGHT_SIDE
    { "Flow1-8-Popup", "Flow2-8-Popup", },  
  };

  static String[] flowEdgeShapeNames = {
    "Flow-Shape1", "Flow-Shape2", "Flow-Shape3", "Flow-Shape4", "Flow-Shape5", 
  };

  public UMLActivityDiagramTemplate() {
  }

  public String[][] getGapToolNames() { 
    return activityDiagramGapToolNames;
  }

  public void initTools() {
    String[] temp = { ".AcceptEvent1", ".AcceptEvent2", ".SendEvent", ".Action", 
		      ".DataStore", ".Decision", ".ForkNode", ".ForkNodeH",
		      ".JoinNode", ".JoinNodeH", ".MergeNode", 
		      ".Object1", ".Object2" };
    for (int i = 0; i < temp.length; i++) { 
      addNodeToolNames(name + temp[i],  activityNodeEdgeToolNames);
    }

    addNodeToolNames(name + ".InitialNode", initActivityNodeEdgeToolNames);
    addNodeToolNames(name + ".FinalNode", finalActivityNodeEdgeToolNames);
    addNodeToolNames(name + ".FinalFlow", finalActivityNodeEdgeToolNames);

    String[] flowTemp = { ".Flow1", ".Flow2", ".Flow3", ".Flow4", ".Flow5", ".Flow6", ".Flow7", 
			  ".Flow10" };
    for (int i = 0; i < flowTemp.length; i++) { 
      addEdgeToolNames(name + flowTemp[i], flowEdgeShapeNames);
    }
  }

  @Override
  public void makeTemplate(Map iconMap) {
    DrawShape shape;
    addNodeTemplate("AcceptEvent1", ActivityNode.ActivityType.Accept_Event, false, 0, 0, 50, 20);
    addNodeTemplate("AcceptEvent2", ActivityNode.ActivityType.Accept_Event, true, 0, 0, 20, 20);
    addNodeTemplate("SendEvent", ActivityNode.ActivityType.Send_Event, 0, 0, 50, 20);

    addNodeTemplate("Action", ActivityNode.ActivityType.Computation, 0, 0, 80, 25);
    addNodeTemplate("DataStore", ActivityNode.ActivityType.DataStore, 0, 0, 80,	25);

    // initial node
    addNodeTemplate("InitialNode", ActivityNode.ActivityType.Initial, 10, 10, 15, 15);
    // final node
    addNodeTemplate("FinalNode", ActivityNode.ActivityType.Final, 10, 10, 15, 15);
    // final flow
    addNodeTemplate("FinalFlow", ActivityNode.ActivityType.Terminate, 10, 10, 15, 15);

    // decision node
    addNodeTemplate("Decision", ActivityNode.ActivityType.Decision, 0, 0, 16, 16);
    // merge node
    addNodeTemplate("MergeNode", ActivityNode.ActivityType.Merge, 0, 0, 16, 16);

    // fork node
    addNodeTemplate("ForkNode", ActivityNode.ActivityType.Fork, 0, 0, 10, 50);
    addNodeTemplate("ForkNodeH", ActivityNode.ActivityType.Fork, 0, 0, 50, 10);

    // join node
    addNodeTemplate("JoinNode", ActivityNode.ActivityType.Join, 0, 0, 10, 50);
    addNodeTemplate("JoinNodeH", ActivityNode.ActivityType.Join, 0, 0, 50, 10);

    // object
    addNodeTemplate("Object1", ActivityNode.ActivityType.Object, false, 0, 0, 60, 25);
    addNodeTemplate("Object2", ActivityNode.ActivityType.Object, true, 0, 0, 60, 25);

    /*
     * shape = new RoundRectangleShape(10, 0, 100, 70, 20, 20);
     * setNodeBgColor(shape, OBJECT_BG); add(new Button("Object3", shape, 24, 24, false, true));
     */

    shape = new RoundRectangleShape(0, 0, 200, 150, 20, 20);
    add(new TemplateToolButton("Region", setNodeAttr(shape, DrawAttr.DASHED_LINE), 
			       36, 30, false, true));
    setPenColor(shape, REGION_FG);
    setNodeBgColor(shape, REGION_BG);
    setLineWidth(shape, 2);

    LineShape line1 = new LineShape(0, 20, 50, 20);
    GraphEdgeShape line = new GraphEdgeShape(0, 20, 50, 20);
    addFlowTemplate("Flow1", line, line1);

    QuadCurveShape qcurve1 = new QuadCurveShape(0, 24, 48, 0, 12, 0);
    GraphEdgeShape qcurve = new GraphEdgeShape(0, 24, 48, 0, 12, 0);
    addFlowTemplate("Flow2", qcurve, qcurve1);

    CubicCurveShape curve1 = new CubicCurveShape(0, 24, 48, 24, 12, 0, 36, 0);
    GraphEdgeShape curve = new GraphEdgeShape(0, 24, 48, 24, 12, 0, 36, 0);
    curve.setCurveType(CubicCurveShape.C_SHAPE_CURVE);
    addFlowTemplate("Flow10", curve, curve1);

    curve1 = new CubicCurveShape(0, 48, 48, 0, 36, 36, 12, 12);
    curve = new GraphEdgeShape(0, 48, 48, 0, 36, 36, 12, 12);
    addFlowTemplate("Flow3", curve, curve1);

    OrthogonalLineShape oline = new OrthogonalLineShape(false, 50, 0);
    oline.addPoint(0, 50);
    oline.addPoint(50, 100);
    oline.setRoundCorner(true);
    oline.calculateBounds();
    GraphEdgeShape edge = new GraphEdgeShape(false, 50, 0);
    edge.addPoint(0, 50);
    edge.addPoint(50, 100);
    edge.setRoundCorner(true);
    edge.calculateBounds();
    addFlowTemplate("Flow4", edge, oline, 36, 30);

    oline = new OrthogonalLineShape(0, 50);
    oline.addPoint(50, 0);
    oline.addPoint(100, 50);
    oline.setRoundCorner(true);
    oline.calculateBounds();
    edge = new GraphEdgeShape(true, 0, 50);
    edge.addPoint(50, 0);
    edge.addPoint(100, 50);
    edge.setRoundCorner(true);
    edge.calculateBounds();
    addFlowTemplate("Flow5", edge, oline);

    oline = new OrthogonalLineShape(0, 80);
    oline.addPoint(100, 20);
    oline.setRoundCorner(true);
    oline.calculateBounds();
    edge = new GraphEdgeShape(true, 0, 80);
    edge.addPoint(100, 20);
    edge.setRoundCorner(true);
    edge.calculateBounds();
    addFlowTemplate("Flow6", edge, oline);

    oline = new OrthogonalLineShape(false, 0, 80);
    oline.addPoint(80, 0);
    oline.setRoundCorner(true);
    oline.calculateBounds();
    edge = new GraphEdgeShape(false, 0, 80);
    edge.addPoint(80, 0);
    edge.setRoundCorner(true);
    edge.calculateBounds();
    addFlowTemplate("Flow7", edge, oline);

    // notes
    addNotesTemplate("Notes1", true, "Link");
    addNotesTemplate("Notes2", false);

    // link
    addNotesLinkTemplate("Link", new LineShape(0, 20, 50, 20));

    makeNodeEdgePopupTemplates();
    makeEdgeShapeTemplates();
  }

  protected void makeNodeEdgePopupTemplates() { 
    LineShape line1 = new LineShape(10, 40, 10, 0);
    addFlowTemplate("Flow1-1-Popup", "Flow1", line1, 16, 20, false, 
		    FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);
    line1 = new LineShape(10, 0, 10, 40);
    addFlowTemplate("Flow1-2-Popup", "Flow1", line1, 16, 20, true, 
		    FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);
    line1 = new LineShape(10, 40, 10, 0);
    addFlowTemplate("Flow1-3-Popup", "Flow1", line1, 16, 20, true, 
		    FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);
    line1 = new LineShape(10, 0, 10, 40);
    addFlowTemplate("Flow1-4-Popup", "Flow1", line1, 16, 20, false, 
		    FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);

    line1 = new LineShape(0, 10, 40, 10);
    addFlowTemplate("Flow1-5-Popup", "Flow1", line1, 25, 10, true, 
		    FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);
    line1 = new LineShape(40, 10, 0, 10);
    addFlowTemplate("Flow1-6-Popup", "Flow1", line1, 25, 10, false, 
		    FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);
    line1 = new LineShape(0, 10, 40, 10);
    addFlowTemplate("Flow1-7-Popup", "Flow1", line1, 25, 10, false, 
		    FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);
    line1 = new LineShape(40, 10, 0, 10);
    addFlowTemplate("Flow1-8-Popup", "Flow1", line1, 25, 10, true, 
		    FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);

    QuadCurveShape qcurve1 = new QuadCurveShape(0, 48, 24, 0, 0, 12);
    addFlowTemplate("Flow2-1-Popup", "Flow2", qcurve1, 16, 20, false, 
			  FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);
    qcurve1 = new QuadCurveShape(0, 0, 24, 48, 24, 12);
    addFlowTemplate("Flow2-2-Popup", "Flow2", qcurve1, 16, 20, true, 
			  FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);
    qcurve1 = new QuadCurveShape(0, 48, 24, 0, 0, 12);
    addFlowTemplate("Flow2-3-Popup", "Flow2", qcurve1, 16, 20, true, 
			  FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);
    qcurve1 = new QuadCurveShape(0, 0, 24, 48, 24, 12);
    addFlowTemplate("Flow2-4-Popup", "Flow2", qcurve1, 16, 20, false, 
			  FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);

    qcurve1 = new QuadCurveShape(0, 24, 48, 0, 12, 0);
    addFlowTemplate("Flow2-5-Popup", "Flow2", qcurve1, 24, 12, true, 
			  FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);
    qcurve1 = new QuadCurveShape(48, 24, 0, 0, 36, 0);
    addFlowTemplate("Flow2-6-Popup", "Flow2", qcurve1, 24, 12, false, 
			  FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);
    qcurve1 = new QuadCurveShape(0, 24, 48, 0, 12, 0);
    addFlowTemplate("Flow2-7-Popup", "Flow2", qcurve1, 24, 12, false, 
			  FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);
    qcurve1 = new QuadCurveShape(48, 24, 0, 0, 36, 0);
    addFlowTemplate("Flow2-8-Popup", "Flow2", qcurve1, 24, 12, true, 
			  FLOW_COLOR, TemplateToolButton.POPUP_BUTTON);

  }

  protected void makeEdgeShapeTemplates() { 
    // flow edge shape template 
    LineShape line1 = new LineShape(0, 20, 50, 20);
    addFlowShapeTemplate("Flow-Shape1", line1, FLOW_COLOR, 25, 10);

    QuadCurveShape qcurve1 = new QuadCurveShape(0, 24, 48, 0, 12, 0);
    addFlowShapeTemplate("Flow-Shape2", qcurve1, FLOW_COLOR, 25, 10);
    
    CubicCurveShape curve1 = new CubicCurveShape(0, 24, 48, 24, 12, 0, 36, 0);
    addFlowShapeTemplate("Flow-Shape3", curve1, FLOW_COLOR, 25, 10);

    OrthogonalLineShape oline = new OrthogonalLineShape(0, 50);
    oline.addPoint(50, 0);
    oline.addPoint(100, 50);
    oline.setRoundCorner(true);
    oline.calculateBounds();
    addFlowShapeTemplate("Flow-Shape4", oline, FLOW_COLOR, 25, 10);

    PolyCurveShape pcurve = new PolyCurveShape(0, 0);
    pcurve.addPoint(30, 40);
    pcurve.addPoint(70, 0);
    pcurve.addPoint(100, 40);
    pcurve.adjustControlPoints();
    pcurve.calculateBounds();
    addFlowShapeTemplate("Flow-Shape5", pcurve, FLOW_COLOR, 25, 10);
  }

  protected void addNodeTemplate(String tempName,
      ActivityNode.ActivityType type, float x, float y, float w, float h) {
    addNodeTemplate(tempName, type, false, x, y, w, h);
  }

  protected void addNodeTemplate(String tempName,
				 ActivityNode.ActivityType type,
				 boolean flag, 
				 float x, float y, float w, float h) {
    GraphNodeBase shape = null;
    DrawShape iconShape = null;
    TextShape text = null;
    CompoundDrawShape comp = null;
    int iconWidth = 36, iconHeight = 18;
    float w1, h1;

    switch (type) {
    case Computation:
      iconWidth = 36;
      iconHeight = 30;
      iconShape = new RoundRectangleShape(x, y, x + w, y + h);
      setNodeAttr(iconShape);
      setNodeColor(iconShape, ACTION_FG, ACTION_BG);
      shape = new RoundRectangleShape(x, y, x + w, y + h);
      setNodeAttr(shape);
      setNodeColor(shape, ACTION_FG, ACTION_BG);
      text = makeTitleText("activity", NODE_FONT, NODE_COLOR);
      text.setDisplayName("Activity");
      shape.setLabel(DrawShapeConstants.ROLE_NODE_LABEL, text);
      shape.setAcceptSubshape(false);
      shape.setScaleMode(DrawShapeConstants.SCALE_EXCLUDE_SUBSHAPE);
      break;

    case Object:
      iconWidth = 36;
      iconHeight = 30;
      if (flag) {
	shape = new RectangleShape(x, y, x + w, y + h);
	iconShape = new RectangleShape(x, y, x + w, y + h);
      } else {
	shape = new RoundRectangleShape(x, y, x + w, y + h, 20, 20);
	iconShape = new RoundRectangleShape(x, y, x + w, y + h, 20, 20);
      }
      setNodeAttr(iconShape);
      setNodeColor(iconShape, OBJECT_FG, OBJECT_BG);
      setNodeAttr(shape);
      setNodeColor(shape, OBJECT_FG, OBJECT_BG);
      text = makeTitleText("object", NODE_FONT, NODE_COLOR);
      text.setDisplayName("Object");
      shape.setLabel(DrawShapeConstants.ROLE_NODE_LABEL, text);
      shape.setAcceptSubshape(false);
      shape.setScaleMode(DrawShapeConstants.SCALE_EXCLUDE_SUBSHAPE);
      break;

    case DataStore:
      iconWidth = 36;
      iconHeight = 30;
      iconShape = new RectangleShape(x, y, x + w, y + h);
      setNodeAttr(iconShape);
      setNodeColor(iconShape, DATA_FG, DATA_BG);
      shape = new RectangleShape(x, y, x + w, y + h);
      setNodeAttr(shape);
      setNodeColor(shape, DATA_FG, DATA_BG);
      text = makeTitleText("data", NODE_FONT, NODE_COLOR);
      text.setDisplayName("Data");
      shape.setLabel(DrawShapeConstants.ROLE_NODE_LABEL, text);
      shape.setAcceptSubshape(false);
      shape.setScaleMode(DrawShapeConstants.SCALE_EXCLUDE_SUBSHAPE);
      break;

    case Fork:
    case Join:
      iconWidth = 36;
      iconHeight = 30;
      RectangleShape rect = new RectangleShape(x, y, x + w, y + h, true);
      if (w < h) {
	rect.setFixedWidth(true);
      } else {
	rect.setFixedHeight(true);
      }
      shape = rect;
      shape.showBorder(false);
      setNodeAttr(shape);
      setNodeBgColor(shape, 
		     type == ActivityNode.ActivityType.Fork ? FORK_BG : JOIN_BG, 
		     true);
      break;

    case Decision:
    case Merge:
    case Initial:
    case Final:
    case Terminate:
      switch (type) {
      case Decision:
	shape = new RectangularShape(ShapeConstants.DIAMOND_SHAPE,
				     ShapeConstants.NORTH, x, y, x + w, y + h);
	shape.showBorder(false);
	setNodeAttr(shape);
	setNodeBgColor(shape, DECISION_BG, true);
	break;
      case Merge:
	shape = new RectangularShape(ShapeConstants.DIAMOND_SHAPE,
				     ShapeConstants.NORTH, x, y, x + w, y + h);
	shape.showBorder(false);
	setNodeAttr(shape);
	setNodeBgColor(shape, MERGE_BG, true);
	break;
      case Initial:
	shape = new EllipseShape(x, y, x + w, y + h, true);
	setNodeAttr(shape);
	setNodeBgColor(shape, INIT_NODE_BG, true);
	break;
      case Final:
	shape = new EllipseShape(x, y, x + w, y + h);
	shape.setDeco(EllipseShape.DECO_DOT);
	setNodeAttr(shape);
	setPenColor(shape, FINAL_NODE_BG);
	setNodeBgColor(shape, FINAL_NODE_BG, true);
	shape.setFilled(false);
	break;
      case Terminate:
	w1 = w * 0.13f;
	h1 = h * 0.13f;
	shape = new EllipseShape(x, y, x + w, y + h, true);
	shape.addShape(new LineShape(x + w1, y + h1, x + w - w1, y + h - h1));
	shape.addShape(new LineShape(x + w1, y + h - h1, x + w - w1, y + h1));
	setNodeAttr(shape);
	setNodeBgColor(shape, FINAL_FLOW_BG, true);

	comp = new CompoundDrawShape(); // icon
	comp.setName(tempName);
	comp.setAtomic(true);
	iconShape = new EllipseShape(x, y, x + w, y + h, true);
	setNodeAttr(iconShape);
	setNodeBgColor(iconShape, FINAL_FLOW_BG);
	comp.addShape(iconShape);
	comp.addShape(new LineShape(x + w1, y + h1, x + w - w1, y + h - h1));
	comp.addShape(new LineShape(x + w1, y + h - h1, x + w - w1, y + h1));
	comp.fitComponents();
	iconShape = comp;
	break;
      }
      shape.setFixedRatio(true);
      shape.setResizable(false);
      shape.setAtomic(true);
      shape.setAcceptSubshape(false);
      break;
    case Accept_Event:
      if (flag) {
	shape = new RectangularShape(ShapeConstants.BOW_TIE_SHAPE,
				     ShapeConstants.NORTH, x, y, x + w, y + h);
	/*
         * iconShape = new RectangularShape(RectangularShape.BOW_TIE_SHAPE,
         * RectangularShape.NORTH, x, y, x + w, y + h);
         */
      } else {
	shape = new RectangularShape(ShapeConstants.CAVE_SHAPE,
				     ShapeConstants.WEST, x, y, x + w, y + h);
	iconShape = new RectangularShape(ShapeConstants.CAVE_SHAPE,
					 ShapeConstants.WEST, x, y, x + w, y + h);
      }
      setNodeAttr(shape);
      // shape.showBorder(false);
      setNodeBgColor(shape, ACCEPT_BG);
      if (!flag) {
	setNodeAttr(iconShape);
	setNodeBgColor(iconShape, ACCEPT_BG);
	text = makeTitleText("event", NODE_FONT, NODE_COLOR);
	shape.setLabel(DrawShapeConstants.ROLE_NODE_LABEL, text);
      }
      shape.setAcceptSubshape(false);
      shape.setScaleMode(DrawShapeConstants.SCALE_EXCLUDE_SUBSHAPE);
      break;
    case Send_Event:
      shape = new RectangularShape(ShapeConstants.HOUSE_SHAPE,
				   ShapeConstants.EAST, x, y, x + w, y + h);
      iconShape = new RectangularShape(ShapeConstants.HOUSE_SHAPE,
				       ShapeConstants.EAST, x, y, x + w, y + h);
      setNodeAttr(shape);
      // shape.showBorder(false);
      setNodeBgColor(shape, SEND_BG);
      setNodeAttr(iconShape);
      setNodeBgColor(iconShape, SEND_BG);
      text = makeTitleText("event", NODE_FONT, NODE_COLOR);
      text.setDisplayName("Event");
      shape.setLabel(DrawShapeConstants.ROLE_NODE_LABEL, text);
      shape.setAcceptSubshape(false);
      shape.setScaleMode(DrawShapeConstants.SCALE_EXCLUDE_SUBSHAPE);
      break;
    }

    if (shape != null) {
      shape.setModel(new ActivityNode(type));
      shape.setModelListener(new UMLActivityNodeModelListener());
      if (iconShape != null) {
	add(new TemplateToolButton(tempName, shape, iconShape, iconWidth, iconHeight,
		       false, true));
      } else {
	add(new TemplateToolButton(tempName, shape, iconWidth, iconHeight, false, true));
      }
    }
  }

  protected void addFlowTemplate(String tempName, GraphEdgeBase shape) {
    addFlowTemplate(tempName, shape, null, 36, 24); 
  }

  protected void addFlowTemplate(String tempName, 
				 GraphEdgeBase shape, DrawShape iconShape) {
    addFlowTemplate(tempName, shape, iconShape, 36, 24); 
  }
  protected void addFlowTemplate(String tempName, 
				 GraphEdgeBase shape, DrawShape iconShape, 
				 int iconWidth, int iconHeight) { 
    if (shape != null) {
      // setLineAttr(shape, DrawAttr.SOLID_LINE, ArrowAttr.LINE_ARROW, 12,
      // 0, 0);
      setLineAttr(shape, DrawAttr.SOLID_LINE,
		  ArrowAttr.ArrowType.FilledTriangle, 8, null, 0);
      setPenColor(shape, FLOW_COLOR);

      shape.setModel(new ActivityFlow());
      shape.setModelListener(new UMLActivityFlowModelListener(this));

      if (iconShape != null) { 
	setLineAttr(iconShape, DrawAttr.SOLID_LINE,
		    ArrowAttr.ArrowType.FilledTriangle, 8, null, 0);
	setPenColor(iconShape, FLOW_COLOR);
	add(new TemplateToolButton(tempName, shape, iconShape, iconWidth, iconHeight, false, true));
      } else { 
	add(new TemplateToolButton(tempName, shape, iconWidth, iconHeight, false, true));
      }
    }
  }

  protected void addFlowTemplate(String tempName, 
				 String protoName, 
				 DrawShape iconShape,
				 int iconWidth, int iconHeight, 
				 boolean reverseEnds, 
				 String colorkey, 
				 int buttonType) {
    if (iconShape != null) { 
      setLineAttr(iconShape, DrawAttr.SOLID_LINE,
		  ArrowAttr.ArrowType.FilledTriangle, 8, null, 0);
      setPenColor(iconShape, colorkey);
      add(new TemplateToolButton(tempName, protoName, iconShape, iconWidth, iconHeight, 
				 false, true,
				 TemplateToolButton.DEFAULT_TOOL, reverseEnds, buttonType));
    }
  }

  protected void addFlowShapeTemplate(String name, 
				      GraphEdgeBase edge, 
				      String colorkey,
				      int iconWidth, int iconHeight) { 
    if (name != null && 
	edge != null) { 
      setLineAttr(edge, DrawAttr.SOLID_LINE, 
		  ArrowAttr.ArrowType.FilledTriangle, 8, null, 0);
      if (colorkey != null) {
	setPenColor(edge, colorkey);
      }
      addEdgeShapeTemplate(name, edge, iconWidth, iconHeight);
    }
  }

  public static final String ACCEPT_BG = "template.UMLActivityDiagram.AcceptEvent.bg";

  public static final String SEND_BG = "template.UMLActivityDiagram.SendEvent.bg";

  public static final String ACTION_FG = "template.UMLActivityDiagram.Action.fg";

  public static final String ACTION_BG = "template.UMLActivityDiagram.Action.bg";

  public static final String DATA_FG = "template.UMLActivityDiagram.DataStore.fg";

  public static final String DATA_BG = "template.UMLActivityDiagram.DataStore.bg";

  public static final String OBJECT_FG = "template.UMLActivityDiagram.Object.fg";

  public static final String OBJECT_BG = "template.UMLActivityDiagram.Object.bg";

  public static final String FINAL_NODE_BG = "template.UMLActivityDiagram.FinalNode.bg";

  public static final String DECISION_BG = "template.UMLActivityDiagram.Decision.bg";

  public static final String FINAL_FLOW_BG = "template.UMLActivityDiagram.FinalFlow.bg";

  public static final String INIT_NODE_BG = "template.UMLActivityDiagram.InitialNode.bg";

  public static final String FORK_BG = "template.UMLActivityDiagram.ForkNode.bg";

  public static final String JOIN_BG = "template.UMLActivityDiagram.JoinNode.bg";

  public static final String MERGE_BG = "template.UMLActivityDiagram.MergeNode.bg";

  public static final String REGION_FG = "template.UMLActivityDiagram.Region.fg";

  public static final String REGION_BG = "template.UMLActivityDiagram.Region.bg";

  public static final String NODE_FONT = "template.UMLActivityDiagram.Node.font";

  public static final String NODE_COLOR = "template.UMLActivityDiagram.Node.color";

  public static final String FLOW_FONT = "template.UMLActivityDiagram.Flow.font";

  public static final String FLOW_COLOR = "template.UMLActivityDiagram.Flow.color";

}
